Add pre-operational self tests for UNO firmware - #511
Conversation
|
@microsoft-github-policy-service agree company="Microsoft" |
There was a problem hiding this comment.
Pull request overview
This PR introduces pre-operational Cryptographic Algorithm Self-Tests (CAST) for the Uno firmware, gating boot completion on known-answer test (KAT) success, while also extending the IO SRAM layout to reserve a dedicated IO slot for self-test buffers and tightening memory-ordering around AES/SHA/PKA command submission.
Changes:
- Reserve a dedicated GSRAM IO buffer slot for self-tests (CAST) and adjust related constants/overlays.
- Add a pre-op CAST suite (AES-CBC + per-PKA-engine RSA mod-exp; HKDF/KBKDF intended) and run it during boot before transitioning to
Running. - Add explicit
dmb()barriers before AES/SHA/UPKA doorbell writes to ensure descriptor write ordering on Cortex-M7.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| fw/plat/uno/rdl/soc/gsram_map.rdl | Expands SRAM_IO_BUF to 34 slots and documents the dedicated self-test slot. |
| fw/plat/uno/rdl/soc/dtcm_map.rdl | Documents why DTCM scratch remains at 33 slots (host+admin only). |
| fw/plat/uno/fw/reg/soc/src/io_gsram.rs | Updates generated constants/overlay sizing for 34 SRAM_IO_BUF slots. |
| fw/plat/uno/fw/pal/src/self_test/vectors.rs | Adds fixed KAT vectors (AES-CBC, HKDF, KBKDF, RSA mod-exp). |
| fw/plat/uno/fw/pal/src/self_test/aes_cbc.rs | Implements AES-256-CBC CAST using the PAL AES path. |
| fw/plat/uno/fw/pal/src/self_test/pka.rs | Implements per-engine RSA-2048 mod-exp CAST using pinned UPKA engines. |
| fw/plat/uno/fw/pal/src/self_test/mod.rs | Defines the pre-op self-test suite entrypoint and module layout. |
| fw/plat/uno/fw/pal/src/pal.rs | Runs CAST during boot and adds polling-based wakeups for AES/SHA. |
| fw/plat/uno/fw/pal/src/lib.rs | Wires the self_test module into the Uno PAL crate. |
| fw/plat/uno/fw/pal/src/io.rs | Adds a dedicated UnoHsmIo::self_test() handle for the reserved slot. |
| fw/plat/uno/fw/pal/src/alloc.rs | Reassigns admin slot index and introduces a dedicated self-test slot index. |
| fw/plat/uno/fw/drivers/upka/src/executor.rs | Adds dmb() before UPKA doorbell submission for correct ordering. |
| fw/plat/uno/fw/drivers/upka/Cargo.toml | Adds cortex-m dependency for dmb(). |
| fw/plat/uno/fw/drivers/sha/src/api.rs | Adds dmb() before SHA doorbell submission and updates related comments. |
| fw/plat/uno/fw/drivers/sha/Cargo.toml | Adds cortex-m dependency for dmb(). |
| fw/plat/uno/fw/drivers/aes/src/api.rs | Adds dmb() before AES doorbell submission. |
| fw/plat/uno/fw/drivers/aes/Cargo.toml | Adds cortex-m dependency for dmb(). |
| fw/pal/traits/src/error.rs | Adds HsmError::SelfTestKatMismatch for CAST failures. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
fw/plat/uno/fw/pal/src/io.rs:111
UnoHsmIo::self_test()setsindex = SELF_TEST_IO_INDEX(33), butIO_METAis only 33 entries (0..=32). Any call topid()/queue_id()/queue_idx()on a self-test IO would indexIO_Q.io_meta[33]out of bounds (undefined behavior). Even if the current self-test path avoids these methods, it’s easy for shared code (logging, future refactors) to call them.
Consider either (a) special-casing pid/queue_* for the self-test IO to return fixed defaults without touching IO_META, or (b) making io_meta() map the self-test slot to a safe metadata entry.
/// Returns a reference to the IO_META entry for this slot.
#[inline]
fn io_meta(&self) -> &IoMetaEntry {
&IO_Q.io_meta[self.index as usize]
}
be2d534 to
4fc2fc2
Compare
Hardware-validated fixes and API cleanup for ecc_sign_with_k (A4), plus a throwaway on-device known-answer test. KAT PASSes on the EVB. Production (ecc_sign_with_k, crypto/ecc.rs): - Fix modular reduction: it is a DOUBLE-WIDTH PKA primitive, so stage xR into a zeroed 2*field buffer (xR || 0). The bare 48-byte input reduced xR || garbage and produced a wrong r; found by comparing to PR #511's run_ecdsa_on_engine. - Zero-copy DMA I/O: take k/digest/d as &DmaBuf and r/s as &mut DmaBuf (caller-owned GSRAM), matching ecc_verify / ecdh_derive -- no operand or result copies; only internal scratch + the flash constants are staged. - Take `curve` as a parameter and reject anything but P-384 with HsmError::UnsupportedCmd. - Drop redundant zero-init: only xr_wide needs it (its zeroed high half is the reduction padding); every other scratch buffer is fully overwritten by its producing PKA op. Confirmed by the KAT. Rename the PKA step primitives to the ecc_* prefix (matching PR #511): ecc_mont_const_calc, ecc_point_mul, ecc_mod_reduction, ecc_mont_repr_in, ecc_mont_repr_out, ecc_mod_inverse, ecc_mod_mul, ecc_mod_add -- engine.rs definitions, opcode.rs doc, ecc.rs call sites. Throwaway (to be removed once the cert-chain path is up): - ecdsa_sign_self_test: NIST CAVP 186-3 P-384 SigGen KAT (same vector as #511), run once at boot from main.rs; logs PASS/FAIL over the trace UART. - Enable trace-uart by default so the self-test result is visible on COM6. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11
* fw/uno: add P-384 modular PKA opcodes for deterministic ECDSA (A1) Add the six P-384 UPKA modular / Montgomery opcode encodings (ModReduction, MontReprIn, MontReprOut, ModInverse, ModMultiplication, ModAddition) needed to build the firmware-side deterministic ECDSA sign (RFC 6979) for the on-the-fly partition-id (PID) certificate leaf. The PID leaf is signed with the P-384 alias key and regenerated lazily, so its DER must be byte-stable; the sign is assembled from PKA modular primitives (no firmware big-int) mirroring the mcr-hsm ECC-sign self-test. Encodings mirror PkaCommandCode in mcr-hsm cp/hsm/types/src/crypto/pka.rs. Only P-384 is required (alias key curve). allow(dead_code) until the deterministic-sign wrappers (ecc_sign_with_k, step A4) consume them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11 * fw/uno: add P-384 order/base-point constants + montgomery_size (A2) Add the NIST P-384 curve order (ORDER384_LE), base point G x/y (BASE384_X_LE / BASE384_Y_LE) in PKA little-endian operand order, plus a montgomery_size(curve) helper (36/52/72 for P-256/384/521), to fw/plat/uno/fw/pal/src/crypto/ecc.rs. These feed the firmware-side deterministic ECDSA sign used to generate the on-the-fly PID certificate leaf (curve order n modulus for the scalar arithmetic; base point G for the k*G point-mul). Values are the significant 48 little-endian bytes, matching PRIME384_LE, verified against NIST secp384r1 and mirroring mcr-hsm ecc_constants.rs. P-384 only (alias key curve). allow(dead_code) until the deterministic-sign wrappers (ecc_sign_with_k, step A4) consume them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11 * fw/uno: add PKA deterministic-sign step primitives to UpkaEngine (A3) Architecture decision: build the deterministic ECDSA sign (cert-chain PID leaf) with PAL-side orchestration — the PAL allocates all DMA buffers from its per-IO scope and drives the sequence via with_engine — rather than a single engine-side ecc_sign_with_k that would need ~11 intermediate buffers passed in. The DMA footprint is ~1 KB per sign out of an 18 KB per-IO SRAM_IO_BUF (per-slot bump allocator, not a shared pool), comfortable under 16 concurrent PKA engines + a 32-deep IO queue. Add the public single-command primitives the PAL orchestrates on one held engine (so a mont_const_calc's Montgomery state stays resident for the ops that follow; execute_cmd does not wipe between commands): - mont_const_calc(curve, modulus, mont_result) [curve-generic] - point_mul(curve, point_xy, scalar, result) [curve-generic] - mod_reduction / mont_repr_in / mont_repr_out / mod_inverse (unary) - mod_multiplication / mod_addition (binary) The six modular ops are P-384 only (the PID leaf is signed with the P-384 alias key); other curves are rejected via p384_modular. Being pub on the re-exported UpkaEngine, they need no allow(dead_code); this also consumes the A1 opcodes, so their allow(dead_code) attributes are dropped. Supersedes the earlier "call execute_cmd directly" note: PAL orchestration requires these named per-op methods so the opcodes stay encapsulated in the driver. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11 * fw/uno: implement deterministic P-384 ECDSA sign orchestration (A4) Add UnoHsmPal::ecc_sign_with_k(io, k, digest, d, r, s) — the PAL-side orchestration (Arch 2) of the deterministic ECDSA-P384 sign used to generate the on-the-fly cert-chain PID leaf. Because the leaf is regenerated lazily its signature must be byte-stable, so k is supplied by the caller (RFC 6979) rather than drawn from the PKA RNG. Ports the mcr-hsm ECC-sign self-test step sequence (0-12): mont-const(p) -> xR = (k*G).x -> mont-const(n) -> r = xR mod n -> mont_repr_in(k,r,e,d) -> k^-1 -> s = k^-1*(e + r*d) mod n -> mont_repr_out(s). All operands are PKA little-endian (48-byte field / 52-byte Montgomery). Every operand/scratch buffer (~20, ~1 KB) is DMA-allocated from the per-IO scope (the PKA engine DMAs its operands; a non-DMA source hardfaults), and the whole sequence runs on ONE held engine via with_engine so the Montgomery constant stays resident for the ops that follow. Results are copied out and the secret-bearing scratch (k and everything derived from k/d) is zeroized before scope release, which only rewinds a watermark. Rejects bad operand lengths and degenerate r==0 / s==0. Consumes the A2 constants (ORDER384_LE, BASE384_X/Y_LE, montgomery_size), so their allow(dead_code) attributes are dropped. allow(dead_code) on the method itself until ecc_sign_deterministic (A6) / PID cert gen (B) consume it; it is validated on-device by the KAT self-test (A7). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11 * fw/uno: generalize PKA modular-op primitives to all NIST curves Open up the six UpkaEngine modular-op step primitives (mod_reduction, mont_repr_in, mont_repr_out, mod_inverse, mod_multiplication, mod_addition) from P-384-only to all three NIST curves (P-256/384/521), matching the curve-generic mont_const_calc / point_mul and the rest of the driver's ECC opcode surface. - opcode.rs: add the P-256/P-521 encodings for each modular op (18 consts total) and per-op *_opcode(curve) selectors, mirroring the existing mont_const_calc_opcode / ecc_sign_opcode pattern. - engine.rs: drop the p384_modular gate; the six methods now resolve their opcode via the selectors and accept any supported curve. The deterministic cert-chain PID-leaf sign still only exercises P-384 (the alias key curve), but the primitives are no longer artificially restricted — a general-purpose PKA driver should expose its modular ops for any curve. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11 * fw/uno: finalize deterministic P-384 ECDSA sign + KAT self-test Hardware-validated fixes and API cleanup for ecc_sign_with_k (A4), plus a throwaway on-device known-answer test. KAT PASSes on the EVB. Production (ecc_sign_with_k, crypto/ecc.rs): - Fix modular reduction: it is a DOUBLE-WIDTH PKA primitive, so stage xR into a zeroed 2*field buffer (xR || 0). The bare 48-byte input reduced xR || garbage and produced a wrong r; found by comparing to PR Azure#511's run_ecdsa_on_engine. - Zero-copy DMA I/O: take k/digest/d as &DmaBuf and r/s as &mut DmaBuf (caller-owned GSRAM), matching ecc_verify / ecdh_derive -- no operand or result copies; only internal scratch + the flash constants are staged. - Take `curve` as a parameter and reject anything but P-384 with HsmError::UnsupportedCmd. - Drop redundant zero-init: only xr_wide needs it (its zeroed high half is the reduction padding); every other scratch buffer is fully overwritten by its producing PKA op. Confirmed by the KAT. Rename the PKA step primitives to the ecc_* prefix (matching PR Azure#511): ecc_mont_const_calc, ecc_point_mul, ecc_mod_reduction, ecc_mont_repr_in, ecc_mont_repr_out, ecc_mod_inverse, ecc_mod_mul, ecc_mod_add -- engine.rs definitions, opcode.rs doc, ecc.rs call sites. Throwaway (to be removed once the cert-chain path is up): - ecdsa_sign_self_test: NIST CAVP 186-3 P-384 SigGen KAT (same vector as Azure#511), run once at boot from main.rs; logs PASS/FAIL over the trace UART. - Enable trace-uart by default so the self-test result is visible on COM6. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11 * fw/uno: add RFC 6979 deterministic-k derivation for P-384 ECDSA (A5) The on-the-fly PID cert leaf is regenerated lazily, so its ECDSA signature must be byte-stable. Draw the per-message secret `k` deterministically (RFC 6979 §3.2, HMAC-SHA384 DRBG over the private key and message hash) instead of from a PRNG, so `ecc_sign_with_k` (A4) produces a reproducible signature. `ecc_generate_k_rfc6979` (P-384 only) reuses the PAL HMAC-SHA384 one-shot. RFC 6979's integer/octet conversions are big-endian while PAL operands are little-endian, so `d`/`digest` are byte-reversed on input and `k` on output. Since hlen == qlen == 384 and n > 2^383, each DRBG block yields one candidate and `bits2octets(digest)` reduces mod n with a single conditional subtraction. DRBG state and private-key-derived scratch are volatile-scrubbed before return. Verified against the RFC 6979 Appendix A.2.6 P-384 / SHA-384 "sample" vector via a throwaway boot self-test: RFC6979 P384 k self-test: PASS Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11 * fw/uno: compose RFC 6979 deterministic ECDSA-P384 sign (A6/A7) Add `ecc_sign_deterministic`: derive the per-message secret `k` (RFC 6979, A5) and produce `(r, s)` via the PKA sign (A4) on one held engine. This is the byte-stable signer the lazily regenerated PID cert leaf needs. Refactor the RFC 6979 DRBG out of `ecc_generate_k_rfc6979` into shared `rfc6979_seed` / `rfc6979_generate` / `rfc6979_reseed` steps (plus an `Rfc6979Drbg` state) so the k-only path (A5) and the sign path reuse one implementation. `ecc_sign_deterministic` drives the full RFC 6979 §3.2 loop: on the ~2^-384 degenerate result (`r == 0` / `s == 0`) it advances the DRBG to the next candidate rather than looping on the same k. A bounded try count guarantees termination; DRBG/private-key scratch is volatile-scrubbed. Verified end-to-end against the RFC 6979 Appendix A.2.6 P-384 / SHA-384 "sample" vector (known r,s) via a throwaway boot self-test (satisfies A7): ECDSA P384 KAT self-test: PASS RFC6979 P384 k self-test: PASS RFC6979 P384 deterministic-sign self-test: PASS Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cfbdfe3b-9b89-4ff3-9657-57d6cc0d3c11 * fw/uno: split deterministic ECDSA-P384 into crypto/ecc_det.rs Move the RFC 6979 deterministic-sign path out of the ~1080-line crypto/ecc.rs into a dedicated crypto/ecc_det.rs, so the base HsmEcc trait adapter stays focused on the standard curve operations. The new module will also host deterministic ECC key generation later. Moved: the P-384 order/base-point constants, montgomery_size, be_sub_assign, secure_zero, the RFC 6979 HMAC-SHA384 DRBG, and the ecc_sign_with_k / ecc_generate_k_rfc6979 / ecc_sign_deterministic methods (plus the throwaway KAT self-tests). PRIME384_LE is shared with the base HsmEcc impl, so it stays in ecc.rs and is now pub(super). No functional change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a40fb65bb6c * fw/uno: make RFC 6979 DRBG DMA-resident and zero-copy (P-384) The RFC 6979 HMAC-SHA384 DRBG staged its K/V state through fresh DMA allocations and stack copies on every HMAC (~5x per deterministic sign, via hmac_sha384_bytes), plus byte-wise reversal loops. With up to 128 concurrent signs this is needless allocation/copy churn (the SHA engine is the real serialization point). Rework the DRBG to hold K, V, a tag slot, and the input-assembly buffer as persistent DMA scratch allocated once per sign. Each step runs the HMAC in place and rotates v/tag (or key/tag) by reference with core::mem::swap -- zero-copy. This drops per-sign DMA allocs from ~15 to ~5 and copies from ~15 to ~2, and removes the nested per-HMAC scope. Also: replace the byte-wise reversal loops with copy_from_slice + slice::reverse(), and drop the hand-rolled secure_zero in favour of DmaBuf::zeroize on the DRBG buffers. ecc_sign_with_k (the PKA sequence) is unchanged. Public API of ecc_generate_k_rfc6979 / ecc_sign_deterministic is unchanged. Validated on Uno hardware: all three boot KATs pass (ECDSA P384 KAT, RFC6979 P384 k, RFC6979 P384 deterministic-sign) against the RFC 6979 A.2.6 vectors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a40fb65bb6c * fw/uno: drop throwaway boot KAT self-tests from deterministic ECDSA The RFC 6979 / ECDSA-P384 deterministic sign was validated on Uno hardware (all three boot KATs pass against the RFC 6979 A.2.6 and NIST CAVP P-384 vectors). Remove the throwaway on-boot self-test harness so this PR ships only production code: - the three ecc_det.rs `*_self_test` methods, - their boot-time wiring in app/main.rs (plus the now-unused `error` tracing import), - the `trace-uart` default toggle in app/Cargo.toml (back to `default = []`, matching main). The deterministic-sign API (ecc_sign_with_k / ecc_generate_k_rfc6979 / ecc_sign_deterministic) stays as the public entry points for the follow-up cert-chain (PID leaf) work and keeps its #[allow(dead_code)] until that consumer lands. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a40fb65bb6c * fw/uno: rustfmt — wrap multi-arg PKA/HMAC calls to CI style CI's nightly `cargo fmt --check` wraps the multi-argument `execute_cmd(...)` calls in upka/engine.rs and the `rfc6979_update_*` / `hmac_sign(...)` calls in ecc_det.rs one-arg-per-line, and trims trailing whitespace in a doc comment. Apply those. The `use` ordering is left as CI expects (its nightly honors the repo's unstable group_imports / imports_granularity options, which local rustfmt rejects). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a40fb65bb6c * fw/uno: scrub deterministic-ECDSA secrets on all exit paths Address PR review: the secret-scrub in the deterministic sign path only ran on the success path, so an early `?` (PKA/HMAC hardware error) left k/d-derived material resident in the scoped DMA heap — the scoped allocator only rewinds its watermark on release, it does not clear freed DMA. - ecc_sign_with_k: capture the PKA-sequence result, then zeroize the internal scratch unconditionally (now also wiping xr/xr_wide, which hold (k*G).x -- public as r, but k-derived -- as defense-in-depth). - ecc_generate_k_rfc6979 / ecc_sign_deterministic: run the fallible derive/sign in an inner async block, then scrub the DRBG state (and k, for the sign) unconditionally afterward. Success-path behaviour and the (r,s)/k outputs are unchanged; only the error / early-return paths now scrub, so the on-hardware KAT result is unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a40fb65bb6c * fw/uno: constant-time RFC 6979 candidate-range check Address PR review: the `1 <= k < n` acceptance test on the RFC 6979 DRBG output used short-circuiting comparisons (`iter().any` + slice `<`), which are not constant-time. The candidate is the secret ECDSA per-message nonce, so byte-position-dependent timing could leak nonce bits (cf. the Minerva / TPM-Fail ECDSA nonce-leak attacks that recover the key from a few biased/leaked nonce bits). Add `ct_in_range`, which reads every byte with no data-dependent early exit (OR-accumulate for `!= 0`; full-width big-endian subtraction for `< n`), and use it in both ecc_generate_k_rfc6979 and ecc_sign_deterministic. Same boolean result, no timing dependence on the secret candidate. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a40fb65bb6c * fw/uno: validate PKA step-primitive buffer sizes; fix nonce-retry comment Address PR review: - upka/engine.rs: the eight new ECC modular/Montgomery step primitives (ecc_mont_const_calc / ecc_point_mul / ecc_mod_reduction / ecc_mont_repr_in / ecc_mont_repr_out / ecc_mod_inverse / ecc_mod_mul / ecc_mod_add) now validate operand/result buffer lengths with `ensure_cmd_input` before issuing the PKA DMA command, mirroring ecc_verify/ecdh_derive. This prevents out-of-bounds DMA reads/writes on undersized buffers. Adds a `mont_operand_size(curve)` helper (36/52/72) for the wider Montgomery-domain operands. - ecc_det.rs: correct the RFC6979_MAX_TRIES doc comment. For P-384 the dominant reseed cause is the range check (candidate >= n, ~2^-194), not the r/s == 0 degenerate-signature case (~2^-384). Widths were checked against the working P-384 sign buffers, so the success-path behaviour and on-hardware KAT result are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a40fb65bb6c * fw/uno: allow clippy::too_many_arguments on ecc_sign_with_k ecc_sign_with_k follows the zero-copy DMA convention (each operand is a separate caller-provided DmaBuf), so it takes 8 arguments and trips clippy::too_many_arguments -- the pal crate does not inherit the workspace-level allow. Add the per-function allow, matching the existing convention in kdf.rs / gcm.rs / aes.rs in the same crate. CI clippy only surfaced this now that the fmt step passes (the precheck runs fmt before clippy). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a40fb65bb6c * fw/uno: precompute P-384 order big-endian; drop per-call reverse The RFC 6979 candidate-range check compares big-endian (the DRBG emits candidates big-endian per bits2int), so ecc_generate_k_rfc6979 and ecc_sign_deterministic reversed ORDER384_LE into a local n_be on every call. Precompute ORDER384_BE from ORDER384_LE at compile time (const reverse48) and use it directly, removing the runtime reverse from both sign entry points. Behavior is unchanged (ORDER384_BE is byte-identical to the previous runtime result, verified against the published P-384 order n). Addresses PR review feedback on the redundant runtime reverse. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a04329e * fw/uno: dedupe Montgomery-size table; reconcile mont_const scratch width Two PR review follow-ups on the deterministic ECDSA-P384 path: - montgomery_size in ecc_det.rs duplicated the driver's mont_operand_size (both 36/52/72), risking silent divergence. The driver helper was only pub(crate); make it pub, re-export it from the upka crate, and use it in ecc_det.rs — single source of truth for the Montgomery operand widths. - ecc_mont_const_calc validated mont_result against mont_operand_size (52B for P-384), while ecc_verify/ecdh_derive issue the same mont_const_calc opcode with a hsm_point_size (48B) scratch buffer. The Montgomery constant is a value < modulus, so it fits the point width; the reference firmware keeps it engine-internal. Relax the check to hsm_point_size so all callers of the opcode validate consistently. Behavior is unchanged: the sign path still passes a 52B buffer, which satisfies the >= 48B check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a04329e * fw/uno: rustfmt import order (UpkaEccCurve before mont_operand_size) CI cargo +nightly fmt --check sorts same-crate item imports case-sensitively (uppercase terminal before lowercase), matching the existing ecc.rs ordering. Move the new mont_operand_size import after UpkaEccCurve. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a04329e * fw/uno: guard RFC 6979 update_key slice against out-of-range len rfc6979_update_key used drbg.msg.split_at(len), which panics if len exceeds drbg.msg.len(). Current callers pass constant lengths bounded by RFC6979_SEED_MSG_LEN, so it never trips today, but a panic is an avoidable abort path in crypto code. Range-check len up front and return HsmError::InvalidArg instead. Behavior is unchanged for the in-range callers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2444329e-909e-4ced-b5df-5a04329e --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
0707c37 to
39d0b9d
Compare
* Clean up unused APIs
* Modify the driver to support this test
The issue is fixed on the mainline (SHA error interrupt was not enabled)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
39d0b9d to
ff7a0a4
Compare
No description provided.